package main

import (
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"strings"
)



func main(){

	log.Print("start")

	e := echo.New()

	e.Use(middleware.Recover())
	e.Use(middleware.CORS())
	e.Use(middleware.Logger())
	e.Use(Count)
	e.Pre(middleware.Rewrite(map[string]string{
		"/old":              "/new",   //��/old�ض�����/new
		"/api/*":            "/$1",
		"/js/*":             "/public/javascripts/$1",
		"/users/*/orders/*": "/user/$1/order/$2",
		"/getUserInfo/":"/user/getUserInfo",
	}))

	api := e.Group("/api",Filter)

	{
		api.GET("/test",Test)

	}

	sigin := make(chan int ,1 )


	test(sigin)
	startDB()
	e.GET("/testJson",testJson)
	go e.Logger.Print(e.Start(":12345"))
	go runRPC()
	<-sigin
}

/**
 * 添加拦截器
 */
func Filter (next echo.HandlerFunc) echo.HandlerFunc {

	return 	func(c echo.Context) error {

		return next(c)
	}
}


func runRPC() {

	server := rpc.NewServer()
	server.Register(new(Arith))
	l, e := net.Listen("tcp", "127.0.0.1:12345") // any available address
	if e != nil {
		log.Fatalf("net.Listen tcp :0: %v", e)
	}

	go server.Accept(l)

}
type Arith int

type Args struct {
	A, B int
}

func (t *Arith) Multiply(args *Args, reply *([]string)) error {
	*reply = append(*reply, "test")
	return nil
}



func test(c chan<-int) {
	c <-5
}

//��¼������
var totalRequests  = 0

//�Զ����м��
func Count(next echo.HandlerFunc) echo.HandlerFunc {

	 return func(c echo.Context) error {
		 //�����ﴦ������������߼�
		 //�ۼƷ�����
		 totalRequests++

		 //����Ӧͷ�����������
		 c.Response().Header().Add("requests", fmt.Sprintf("%d", totalRequests))

		 return next(c)
	 }

}

type User struct{

	//id int `json:"id"` //ͨ��json��ǩ����struct�ֶ�ת����json�ֶε����֡�
	//uid int `json:"uid"`

	id int64   `json:"id" xml:"id`
	name string	`json:"name" xml:"name"`
	age int8	`json:"age" xml:"age"`
	sex int8	`json:"sex" xml:"sex"`
	phone string `json:"phone" xml:"phone"`
}

func QueryUser() (User,int){
	var user User
	rows, err := db.Query("select * from user where id in (1,2,3)")
	if err == nil {
        err = errors.New("query incur error")

	}

	for rows.Next() {

		err = rows.Scan(user.id,user.name,user.age,user.sex,user.phone)
		if err != nil {
			fmt.Println(json.Marshal(user))
		}
	}

	rows.Close()

	db.QueryRow("select * from user where id = 1").Scan(user.id,user.name,user.age,user.sex,user.phone)

	stmt,err :=db.Prepare("select * from user where id = ?")
	query,err :=stmt.Query(1)
	query.Scan()

	return user,1
}


func DeleteUser(user User) 	bool {
	//开启事务
	tx,err := db.Begin()
	if err != nil {
		fmt.Println("tx fail")
	}
	//准备sql语句
	stmt,err := tx.Prepare("delete from user where id = ?")
	if err != nil {
		fmt.Println("Prepare fail")
		return false
	}

	//设置参数以及执行sql语句
	result,err := stmt.Exec(user.id)
	if err != nil {
		fmt.Println("Exec fail")
		return false
	}
	//提交事务
	tx.Commit()

	//获取上一个insert 的id
	fmt.Println(result.LastInsertId())
	return true
}


func InserUser(user User) bool {
	tx,err := db.Begin()
	if err != nil {
		fmt.Println("tx fail")
		return false
	}

	stmt,err := tx.Prepare("insert into user(`name`, `phone`) values (?,?)")
	if err != nil {
		fmt.Println("Prepare fail")
		return false
	}

	//将参数传递到sql语句中并且执行
	result,err := stmt.Exec(user.name,user.phone)
	if err != nil {
		fmt.Println("Exec fail")
		return false
	}

	tx.Commit()

	//获得上一个插入自增的id
	fmt.Println(result.LastInsertId())
	return true
}



func testJson(c echo.Context) error{
	//构建user对象
	u :=&User{}

	//db.Query()来发送查询到数据库，获取结果集Rows，并检查错误
	rows,error :=db.Query("SELECT id,uid FROM `winning_record` where id = ?",1)
	if error != nil {
		log.Fatal(error)
	}
	//rows.Close()关闭结果集，释放连接。
	defer rows.Close()

	var id,uid int64
	//rows.Next()作为循环条件，迭代读取结果集。
	for rows.Next() {
		//rows.Scan从结果集中获取一行结果。
		error = rows.Scan(&id,&uid)
		if error != nil {
			log.Fatal(error)
		}

		log.Println(id,uid)
	}
	u.id = id

	//rows.Err()在退出迭代后检查错误。
	error = rows.Err()

	if error != nil {
		log.Fatal(error)
	}

	user := User{name:"huangming",age:18,sex:1,phone:"15118173910"}
	InserUser(user)

	//user,res := QueryUser()
	//
	//if res != 1 {
	//	log.Fatal(res)
	//}

	return c.JSON(http.StatusOK,&user)
}

var db *sql.DB


const (
	userName = "root"
	password = "a19910311"
	ip = "127.0.0.1"
	port = "3306"
	dbName = "huangming"
)


func startDB(){
	// 1. 初始化数据库连接  用户名:密码@tcp(IP:端口)/数据库?charset=utf8
	// Query表示查询，它会从数据库获取查询结果（一系列行，可能为空）。 QueryRow表示只返回一行的查询，作为Query的一个常见特例。
	// Exec表示执行语句，它不会返回行。 Prepare表示准备一个需要多次使用的语句，供后续执行用。
	//db,_ = sql.Open("mysql", "root:a19910311@tcp(127.0.0.1:3306)/huangming?charset=utf8")
	//构建连接："用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
	path := strings.Join([]string{userName, ":", password, "@tcp(", ip, ":", port, ")/", dbName, "?charset=utf8"}, "")
	db,_ = sql.Open("mysql",path)
	//设置数据库最大连接数
	db.SetConnMaxLifetime(100)
	//设置上数据库最大闲置连接数
	db.SetMaxIdleConns(10)
	////验证连接
	err := db.Ping()
	if err != nil {
		log.Fatal("open database fail")
		return
	}

	fmt.Println("connnect success")
}